﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Text;
using CoreLib.DAL;
using RKMSikraKulingram.PresentationEntities;

namespace CoreLib.BusinessLogic
{
    public class CommonBLL
    {
        # region Private Data Members

        private SikraDataContext _context = null;
        private SikraDataContext Context
        {
            get
            {
                return _context;
            }
        }

        private static CommonBLL _commonBLL = null;

        private static Table<Person> _persons = null;
        private static FirstName[] _personFirstName = null;

        private static Table<TransactionMode> _transactionModes = null;
        private static TransactionModeNames[] _transactionModeNames = null;

        private static Table<DonationPlace> _donationPlaces = null;
        private static DonationPlaceNames[] _donationPlaceNames = null;

        public static Table<DonationAccount> _donationAccounts = null;
        private static DonationAccountNames[] _donationAccountNames = null;

        public static Table<PostalMode> _postalModes = null;
        private static PostalModeNames[] _postalModeNames = null;

        # endregion

        # region Constructor

        private CommonBLL()
        {
            _context = new SikraDataContext();
        }

        # endregion

        # region Public Properties

        public static CommonBLL CreateCommonBLL()
        {
            if (null == _commonBLL)
                _commonBLL = new CommonBLL();

            return _commonBLL;
        }

        # endregion

        # region Public Methods

        public FirstName[] GetPersonFirstNames()
        {
            if (null == _personFirstName)
                RefreshPersons();

            return _personFirstName;
        }

        public TransactionModeNames[] GetTransactionModeNames()
        {
            if (null == _transactionModeNames)
                RefreshTransactionModes();

            return _transactionModeNames;
        }

        public DonationPlaceNames[] GetDonationPlaceNames()
        {
            if (null == _donationPlaceNames)
                RefreshDonationPlaces();

            return _donationPlaceNames;
        }

        public DonationAccountNames[] GetDonationAccountNames(int donationPlaceID)
        {
            if (null == _donationAccounts)
                RefreshDonationAccounts();

            _donationAccountNames = _donationAccounts.
                Where(d => d.DonationPlaceID == donationPlaceID && d.Enable == true).
                Select(d => new DonationAccountNames(d.DonationAccountID, d.DonationAccountName)).ToArray<DonationAccountNames>();

            return _donationAccountNames;
        }

        public PostalModeNames[] GetPostalModeNames()
        {
            if (null == _postalModeNames)
                RefreshPostalModes();

            return _postalModeNames;
        }

        public Address GetAddressByPersonID(int personID)
        {
            var a = Context.AddressSelectByPersonID(personID);
            return (null == a) ? new Address() :
                UtilityClass.AddressSelectByPersonIDResultToAddress(a.First<AddressSelectByPersonIDResult>());
        }

        # region Person

        public Person GetPersonByPersonID(int personID)
        {
            if (null == _persons)
                RefreshPersons();

            Person person = new Person();

            var p = _persons.Where(o => o.PersonID == personID);
            if (p.Count<Person>() > 0)
                person = p.First<Person>();

            return person;
        }

        public int InsertPerson(ref int personIDCreated, Person person)
        {
            int? personID = 0;

            Context.PersonsInsert(person.AddressID, person.Title, person.FirstName, person.LastName, person.EntryDate, ref personID);

            if (null != personID)
            {
                RefreshPersons();

                personIDCreated = personID.Value;

                return personIDCreated;
            }

            return 0;
        }

        public void UpdatePerson(int personID, Person person)
        {
            Context.PersonsUpdate(personID, person.AddressID, person.Title, person.FirstName, person.LastName, person.EntryDate);

            RefreshPersons();
        }

        # endregion Person

        # region Address

        public Address GetAddressByAddressID(int addressID)
        {
            var a = Context.AddressSelectByAddressID(addressID);
            return (null == a) ? new Address() :
                UtilityClass.AddressSelectByAddressIDResultToAddress(a.First<AddressSelectByAddressIDResult>());
        }

        public int InsertAddress(ref int addressIDCreated, Address address)
        {
            int? addressID = 0;

            Context.AddressInsert(address.AddressLine1, address.AddressLine2, address.AddressLine3, address.AddressLine4,
                address.PostalCode, address.Country, address.PhoneNumber, address.Email, ref addressID);

            if (null != addressID)
            {
                addressIDCreated = addressID.Value;
                return addressIDCreated;
            }

            return 0;
        }

        public void UpdateAddress(int addressID, Address address)
        {
            Context.AddressUpdate(addressID, address.AddressLine1, address.AddressLine2, address.AddressLine3, address.AddressLine4,
                address.PostalCode, address.Country, address.PhoneNumber, address.Email);
        }

        # endregion Address

        # region Transaction

        public Transaction GetTransactionByTransactionID(int transactionID)
        {
            var t = Context.TransactionsSelectByTransactionID(transactionID);
            return (null == t) ? new Transaction() :
                UtilityClass.TransactionsSelectByTransactionIDResultToTransaction(t.First<TransactionsSelectByTransactionIDResult>());
        }

        public int InsertTransaction(Transaction transaction)
        {
            int? transactionID = 0;

            Context.TransactionsInsert(transaction.TransactionModeID, transaction.PersonID, transaction.AddressID, transaction.TransactionModeNumber,
                transaction.TransactionModeDate, transaction.TransactionAmount, transaction.TransactionModeBank, transaction.TransactionDate, ref transactionID);

            return transactionID.Value;
        }

        public bool UpdateTransaction(int transactionID, Transaction transaction)
        {
            Context.TransactionsUpdate(transactionID, transaction.PersonID, transaction.AddressID, transaction.TransactionModeID, transaction.TransactionModeNumber,
                transaction.TransactionModeDate, transaction.TransactionAmount, transaction.TransactionModeBank, transaction.TransactionDate);

            return true;
        }

        # endregion

        # region ReceiptDetails

        public TransactionReceiptDetail GetTransactionReceiptDetailByTransactionReceiptDetailID(int transactionReceiptDetailID)
        {
            var r = Context.TransactionReceiptDetailSelectByTransactionReceiptDetailID(transactionReceiptDetailID);
            return (null == r) ? new TransactionReceiptDetail() :
                UtilityClass.TransactionReceiptDetailSelectByTransactionReceiptDetailIDResultToTransactionReceiptDetail(r.First<TransactionReceiptDetailSelectByTransactionReceiptDetailIDResult>());
        }

        public int InsertReceiptDetails(TransactionReceiptDetail transactionReceiptDetails)
        {
            int? receiptDetailID = 0;

            Context.TransactionReceiptDetailInsert(transactionReceiptDetails.TransactionID, transactionReceiptDetails.DonationPlaceID, transactionReceiptDetails.DonationAccountID,
                transactionReceiptDetails.TransactionReceiptNumber, transactionReceiptDetails.TransactionReceiptDate, transactionReceiptDetails.PostalModeID, transactionReceiptDetails.DespatchDate, ref receiptDetailID);

            return receiptDetailID.Value;
        }

        public bool UpdateTransactionReceiptDetails(int transactionReceiptDetailID, TransactionReceiptDetail transactionReceiptDetail)
        {
            Context.TransactionReceiptDetailUpdate(transactionReceiptDetailID, transactionReceiptDetail.TransactionID, transactionReceiptDetail.DonationPlaceID, transactionReceiptDetail.DonationAccountID,
                transactionReceiptDetail.TransactionReceiptNumber, transactionReceiptDetail.TransactionReceiptDate, transactionReceiptDetail.PostalModeID, transactionReceiptDetail.DespatchDate);

            return true;
        }

        # endregion

        # region Person Details To Post

        public PersonDetailsPost[] GetPersonDetailPostList()
        {
            PersonDetailsPost[] personDetailPostList = Context.PersonDetailsPosts.
                ToList<PersonDetailsPost>().OrderBy(p => p.FirstName).ThenBy(p => p.LastName).ToArray();

            return personDetailPostList;
        }

        # endregion

        # endregion

        # region Private Methods

        private void RefreshPersons()
        {
            _persons = Context.Persons;
            _personFirstName = _persons.OrderBy(f => f.FirstName).Select(p => new FirstName(p.PersonID, p.AddressID, p.FirstName)).ToArray();
        }

        private void RefreshTransactionModes()
        {
            _transactionModes = Context.TransactionModes;
            _transactionModeNames = _transactionModes.Select(m => new TransactionModeNames(m.TransactionModeID, m.TransactionModeName)).ToArray<TransactionModeNames>();
        }

        private void RefreshDonationPlaces()
        {
            _donationPlaces = Context.DonationPlaces;
            _donationPlaceNames = _donationPlaces.Where(d => d.Enable == true).
                Select(d => new DonationPlaceNames(d.DonationPlaceID, d.DonationPlaceName)).ToArray<DonationPlaceNames>();
        }

        private void RefreshDonationAccounts()
        {
            _donationAccounts = Context.DonationAccounts;
        }

        private void RefreshPostalModes()
        {
            _postalModes = Context.PostalModes;
            _postalModeNames = _postalModes.Select(pm => new PostalModeNames(pm.PostalModeID, pm.PostalModeName)).ToArray<PostalModeNames>();
        }

        # endregion
    }
}
